﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace PDChart
{
    public class PDFile
    {
        public Cycle50 Data = new Cycle50();

        public void Load(string filename, long offset)
        {
            byte[] buffer = new byte[1024 * 100 * 8];
            
            using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
            {
                fs.Seek(offset, SeekOrigin.Begin);
                int cnt = fs.Read(buffer, 0, buffer.Length);
                int pos = 0;
                Data.Create(buffer, cnt / 8, ref pos); 

            }
        }

        public double[,] ToPRPS(double maxQ)
        {
            double[,] prps = Data.ToDoubleMatrix();

            for (int i = 0; i < prps.GetLength(0); i++)
            {
                for (int j = 0; j < prps.GetLength(1); j++)
                {
                    prps[i, j] = prps[i, j] / maxQ;
                }
            }

            return prps;
        }

        public double[,] ToPRPD(int numQ, double maxQ)
        {
            double[,] prps = Data.ToDoubleMatrix();

            double[,] prpd = new double[Cycle1.NumberOfPartitions, numQ];

            for (int i = 0; i < prps.GetLength(0); i++)
            {
                for (int j = 0; j < prps.GetLength(1); j++)
                {
                    if (prps[i, j] > maxQ)
                        prps[i, j] = maxQ;

                    if (prps[i, j] > 0)
                    {
                        int k = (int)Math.Ceiling(prps[i, j] / maxQ * numQ) - 1;
                        
                        if (k >= 0 && k < numQ) 
                            prpd[j, k]++;
                    }
                }
            }

            return prpd;
        }
    }


    public class Cycle50
    {
        public const int NumberOfCycles = 50;
        public Cycle1[] Cycles = new Cycle1[NumberOfCycles];

        public Cycle50()
        {
            for (int i = 0; i < Cycles.Length; i++)
            {
                Cycles[i] = new Cycle1();
            }
        }

        protected int CycleCount = 0;

        public bool Create(byte[] data, int num, ref int pos)
        {
            for (; CycleCount < NumberOfCycles; CycleCount++)
            {
                if (!Cycles[CycleCount].Create(data, num, ref pos))
                {
                    return false;
                }
            }

            return true;


        }

        public double[,] ToDoubleMatrix()
        {
            double[,] m = new double[NumberOfCycles, Cycle1.NumberOfPartitions];

            for (int i = 0; i < m.GetLength(0); i++)
            {
                for (int j = 0; j < m.GetLength(1); j++)
                {
                    m[i, j] = (double)Cycles[i].Peak[j];
                }
            }

            return m;
        }

        public int[,] ToIntMatrix()
        {

            int[,] m = new int[NumberOfCycles, Cycle1.NumberOfPartitions];

            for (int i = 0; i < m.GetLength(0); i++)
            {
                for (int j = 0; j < m.GetLength(1); j++)
                {
                    m[i, j] = Cycles[j].Peak[i];
                }
            }

            return m;
        }
    }

    public class Cycle1
    {
        public const int NumberOfPartitions = 72;
        public int[] Peak = new int[NumberOfPartitions];
        public int[] Width = new int[NumberOfPartitions];
        public int[] Count = new int[NumberOfPartitions];

        protected bool EndOfCycle = true;

        public bool Create(byte[] data, int num, ref int pos)
        {

            int index = BitConverter.ToInt16(data, pos * 8);

            if (pos == 0 && index == 0 && !EndOfCycle)
            {
                EndOfCycle = true;
                return true;
            }

            while (true)
            {
                int peak = BitConverter.ToInt16(data, pos * 8 + 2);
                int width = BitConverter.ToInt16(data, pos * 8 + 4);
                int count = BitConverter.ToInt16(data, pos * 8 + 6);

                int i = index / (360 / NumberOfPartitions);

                if (Peak[i] < peak)
                {
                    Peak[i] = peak;
                    Width[i] = width;
                }

                Count[i] = Count[i] + count;

                pos++;

                if (pos == num)
                {
                    EndOfCycle = false;
                    return false;
                }

                if ((index = BitConverter.ToInt16(data, pos * 8)) == 0)
                {
                    return true;
                }
            }

        }
    }
}
